<template>
  <div class="upload">
    <div class="upload-area">
      <div class="upload-area-inner" id="drop">
        <div class="img-wrap">
          <img :src="uploadImg" alt="" />
          <input type="file" class="origin-btn" id="uploadBtn" :accept="acceptType" :multiple="multiple"/>
        </div>
        <div class="tip">点击图标上传文件或者将文件拖到此处</div>
      </div>
    </div>
    <div class="upload-footer">
      <div class="upload-tip danger-color" v-if="uploadTip">
        {{ uploadTip }}
      </div>
      <div class="refresh primary-color" @click="refresh">刷新</div>
    </div>
    
    <div class="upload-result" v-if="uploadFileList.length > 0">
      <div class="ur-title">
        <div class="ur-right">共{{uploadFileList.length}}个文件</div>
        <div class="ur-tools">
          <el-button type="primary" size="large" @click="showOptionsDrawer" :loading="resLoading">开始处理</el-button>
        </div>
      </div>
      <div class="ur-list">
        <div
          class="ur-item"
          v-for="(fileObj, index) in uploadFileList"
          :key="index"
        >
          <div class="left">{{ fileObj.name }}</div>
          <div class="right">
            <div class="status">
              <el-icon class="is-loading status-icon" v-if="fileObj.status===0" color="#409EFF">
                <Loading />
              </el-icon>
              <el-icon class="is-success status-icon" v-if="fileObj.status===1" color="#67C23A">
                <SuccessFilled />
              </el-icon>
              <span class="txt processing" v-if="fileObj.status===0">处理中</span>
              <span class="txt success" v-if="fileObj.status===1">已完成</span>
            </div>
            <div class="btn">
              <el-button type="danger" size="large" link @click="deleteThisFile(index)">删除文件</el-button>
            </div>
          </div>
        </div>
      </div>

      
    </div>
    <div class="divider-line" v-if="resultBlobList.length > 0">
      <el-divider>
        <span class="hidden-sm-and-down">
          <el-icon color="#67C23A"><StarFilled /></el-icon>
          <el-icon color="#67C23A"><StarFilled /></el-icon>
          <el-icon color="#67C23A"><StarFilled /></el-icon>
        </span>
        <span class="success-color"> 结果如下 </span>
        <span class="hidden-sm-and-down">
          <el-icon color="#67C23A"><StarFilled /></el-icon>
          <el-icon color="#67C23A"><StarFilled /></el-icon>
          <el-icon color="#67C23A"><StarFilled /></el-icon>
        </span>
      </el-divider>
    </div>
    <div class="upload-result" v-if="resultBlobList.length > 0">
      <div class="ur-title">
        <div class="ur-right">结果共{{resultBlobList.length}}个文件</div>
        <div class="ur-tools">
          <el-button type="success" size="large" @click="downloadAllFile">下载全部</el-button>
        </div>
      </div>
      <div class="ur-list">
        <div
          class="ur-item"
          v-for="(fileObj, index) in resultBlobList"
          :key="index"
        >
          <div class="left">{{ fileObj.name }}</div>
          <div class="right">
            <div class="btn">
              <el-button type="success" size="large" link @click="downloadThisFile(index)">下载文件</el-button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 选项抽屉 -->
    <client-only>
      <el-drawer
        v-model="optionsDrawerVisible"
        title="请修改配置项"
        direction="rtl"
        :before-close="closeOptionsDrawer"
        class="drawer"
        size="300"
      >
        
        <slot name="drawerOptions"></slot>
        <template #footer>
          <div class="btn-wrap drawer-footer">
            <el-button  size="large" @click="closeOptionsDrawer">取消</el-button>
            <el-button type="primary"  size="large" @click="startProcessFile">确定</el-button>
          </div>
        </template>
      </el-drawer>
    </client-only>
    
  </div>
</template>

<script setup>
// 组件的使用方法
/**
 * 组件包含2部分，
 * 1.上传：上传按钮、上传文件展示、处理后的文件展示
 * 2.右出抽屉：处理文件程序所需要的参数
 */

import { ref, reactive, onMounted } from 'vue'
import uploadImg from '@/assets/images/upload.png'
import { ElMessage } from 'element-plus'
import { Download,Loading,SuccessFilled,StarFilled} from '@element-plus/icons-vue'
import { downFile,createZipFileByBlobList,getTodayStr } from '@/utils/tools'
const props = defineProps({
  acceptType:{
    type:String,
    default:''
  },
  multiple:{
    type:Boolean,
    default:true
  },
  validateFn:{
    type:Function,
    default:() => {
      return true
    }
  },
  processFn:{   //文件处理函数
    type:Function,
    required:true
  },
  hasOptions:{
    type:Boolean,
    default:false  // 是否有配置项
  },
  uploadTip:{  // 上传提示
    type:String,
    default:''
  }
})

const uploadFileList = ref([])
const resLoading = ref(false)
const resultBlobList = ref([])
const optionsDrawerVisible = ref(false)

function initDropEvent() {
  let droptarget = document.getElementById('drop')
  droptarget.addEventListener(
    'dragenter',
    function (e) {
      e.preventDefault()
      e.stopPropagation()
    },
    false
  )
  droptarget.addEventListener(
    'dragover',
    function (e) {
      e.preventDefault()
      e.stopPropagation()
    },
    false
  )
  droptarget.addEventListener(
    'drop',
    function (e) {
      e.preventDefault()
      let fileArr = []
      for (let file of e.dataTransfer.files) {
        // 把文件保存到文件数组中
        file.status = -1
        fileArr.push(file)
      }
      // 单文件
      if(!props.multiple){
        fileArr = fileArr.slice(0,1)
        uploadFileList.value = fileArr
      }else {
        uploadFileList.value = uploadFileList.value.concat(fileArr)
      }
      
      console.log('uploadFileList.value:',uploadFileList.value)
    },
    false
  )
  droptarget.addEventListener(
    'dragleave',
    function (e) {
      e.preventDefault()
      e.stopPropagation()
    },
    false
  )
}
function initUploadEvent(){
  // 初始化上传事件
  let uploadEl = document.getElementById('uploadBtn')
  uploadEl.addEventListener('change',function(event){
    let files = Array.from(event.target.files)
    if(files.length > 0){
      files.forEach(file => {
        file.status = -1
      })
      if(props.multiple){
        uploadFileList.value = uploadFileList.value.concat(files)
      }else {
        uploadFileList.value = files.slice(0,1)
      }
      
    }else {
      ElMessage({
        type: 'error',
        message: '上传文件不能为空'
      })
    }
  })
}

function deleteThisFile(index){
  uploadFileList.value.splice(index,1)
}


function closeOptionsDrawer(){
  optionsDrawerVisible.value = false
}

function showOptionsDrawer(){
  // 有配置项，需要修改配置项
  if(props.hasOptions){
    if(uploadFileList.value.length > 0){
      optionsDrawerVisible.value = true
    }else {
      ElMessage({
        type: 'error',
        message: '请先选择文件'
      })
    }
  }else {
    // 没有配置项，则直接处理文件
    startProcessFile()
  }
  
}
function refresh() {
  window.location.reload()
}

// 开始处理文档
async function startProcessFile(){
  let valid = await props.validateFn(uploadFileList.value)
  
  if(!valid){
    return 
  }

  closeOptionsDrawer()
  resLoading.value = true
  try {
    let proResult = await props.processFn(uploadFileList.value)
    // console.log('proResult:',proResult)
    if(proResult && proResult.length > 0){
      resultBlobList.value = proResult
      ElMessage.closeAll()
      ElMessage({
        type: 'success',
        message: '处理完成'
      })
    }
    
  } catch (error) {
    console.error(error)
    ElMessage({
      type: 'error',
      message: '处理文件出错'
    })
  } finally {
    resLoading.value = false  
  }
  
  
}
function downloadThisFile(index){
  let blobObj = resultBlobList.value[index]
  downFile(blobObj.name,blobObj.blob)
  ElMessage.closeAll()
  ElMessage({
    type:'success',
    message:'已经开启下载'
  })
}
async function downloadAllFile(){
  let zipBlob = await createZipFileByBlobList(resultBlobList.value)
  let todayStr = getTodayStr()
  let zipName = `${todayStr}.zip`
  downFile(zipName,zipBlob)
  ElMessage.closeAll()
  ElMessage({
    type:'success',
    message:'已经开启下载'
  })
}
onMounted(() => {
  initUploadEvent()
  initDropEvent()
})
</script>
<style lang="scss" scoped>
.upload {
  .upload-area {
    margin: auto;
    max-width: 480px;
    border-radius: 4px;
    padding: 20px;
    box-sizing: border-box;
    background: rgba(17, 150, 219, 0.1);

    .upload-area-inner {
      border: 2px dashed white;
      padding: 20px;
      position: relative;
      
    }
    .origin-btn {
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0px;
      left: 0px;
      opacity: 0;
    }
    .img-wrap {
      width: 80px;
      height: 80px;
      margin: auto;
      position: relative;
      img {
        width: 100%;
        height: 100%;
      }
    }
    .tip {
      margin-top: 30px;
      text-align: center;
      font-weight: bold;
    }
  }
  .upload-footer{
    margin: auto;
    max-width: 480px;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin:auto;
    margin-top:16px;
    .upload-tip{
      max-width: 400px;
      font-size: 14px;
      line-height: 20px;
    }
    .refresh{
      cursor: pointer;
      margin-left: auto;
    }
  }
  
  .upload-result{
    margin-top:20px;

    .ur-title{
      background: rgba(17, 150, 219, 0.1);
      height: 60px;
      line-height: 60px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding:10px;
      box-sizing: border-box;
      border-radius: 4px;
      :deep(.el-icon){
        font-size: 20px;
      }
    }
    .ur-item{
      margin-top:2px;
      background: rgba(17, 150, 219, 0.1);
      height: 60px;
      padding:10px;
      box-sizing: border-box;
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      .right{
        min-width: 100px;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        .status{
          display: flex;
          align-items: center;
          .status-icon{
            margin-right: 10px;
          }
          .txt{
            
            &.processing{
              color:#409EFF;
            }
            .success{
              color: #67C23A;
            }
          }
        }
        .btn{
          margin-left: 10px;
        }
      }
    }
  }
  .divider-line{
    margin:40px 0px;
  }
}

.drawer{
  .drawer-footer{
    border-top: 1px solid #eee;
    padding-top: 20px;
  }
}
@media screen and (max-width:600px) {
  .upload {
    .upload-area {
      padding: 10px;
      .upload-area-inner {
        padding: 10px;
      }
      .tip {
        margin-top: 10px;
      }
    }
  }
}
</style>
